package cn.lili.modules.member.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.PayWayEnum;
import cn.lili.common.security.enums.VipStatusEnum;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.client.VipConfigClient;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.member.mapper.VipMapper;
import cn.lili.modules.member.service.UserService;
import cn.lili.modules.member.service.VipActiveCodeService;
import cn.lili.modules.member.service.VipFlowService;
import cn.lili.modules.member.service.VipService;
import cn.lili.modules.member.service.VipService;
import cn.lili.modules.order.order.client.OrderClient;
import cn.lili.modules.order.order.client.OrderClient;
import cn.lili.modules.system.entity.dos.LiVip;
import cn.lili.modules.system.entity.dos.LiVipActiveCode;
import cn.lili.modules.system.entity.dos.LiVipConfig;
import cn.lili.modules.system.entity.dos.LiVipFlow;
import cn.lili.modules.system.entity.dto.VipDto;
import cn.lili.modules.system.entity.dto.VipPageDto;
import cn.lili.modules.system.entity.vo.LiVipVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;

/**
* @author asus
* @description 针对表【li_vip(会员列表)】的数据库操作Service实现
* @createDate 2023-11-07 13:52:33
*/
@Service
@AllArgsConstructor
public class VipServiceImpl extends ServiceImpl<VipMapper, LiVip>
    implements VipService{

    private final VipMapper vipMapper;
    private final UserService userService;
    private final VipFlowService flowService;
    private final VipActiveCodeService vipActiveCodeService;
    @Resource
    private VipConfigClient vipConfigClient;

    private final OrderClient orderClient;

    /**
     * 会员分页查询
     */
    @Override
    public Page<LiVip> pageFind(VipPageDto dto) {
        LambdaQueryWrapper<LiVip> wrapper=new LambdaQueryWrapper<LiVip>();
        wrapper.like(!StringUtils.isEmpty(dto.getUserName()),LiVip::getUserName,dto.getUserName())
                .like(!StringUtils.isEmpty(dto.getUserId()),LiVip::getUserId,dto.getUserId())
                .orderByDesc(LiVip::getCreateTime)
                .eq(!Objects.isNull(dto.getVipStatus()),LiVip::getVipStatus,dto.getVipStatus());
        return super.page(new Page<>(dto.getPageNumber(), dto.getPageSize()), wrapper);
    }

    /**
     * 会员冻结
     */
    @Override
    public void freeze(String id) {
        UpdateWrapper<LiVip> wrapper = new UpdateWrapper<LiVip>();
        wrapper.eq("id",id)
                .set("vip_status",3);
        this.update(wrapper);
    }

    /**
     * 会员解冻
     */
    @Override
    public ResultMessage<Object> unfreeze(String id) {
        LambdaQueryWrapper<LiVip>wrapper1=new LambdaQueryWrapper<>();
        wrapper1.eq(LiVip::getId,id);
        LiVip liVip = vipMapper.selectOne(wrapper1);
        if (Objects.isNull(liVip))
            throw new ServiceException(ResultCode.USER_NOT_EXIST);
        Integer status=liVip.getVipStatus();
        if (!(Objects.equals(status, VipStatusEnum.FREEZE.getStatus()))&&!(Objects.equals(status, VipStatusEnum.URBAN_FREEZE.getStatus())))
            return ResultUtil.error(400,"无效操作");
        int result = liVip.getEndTime().compareTo(Date.from(Instant.now()));
        UpdateWrapper<LiVip> wrapper=new UpdateWrapper<LiVip>();
        wrapper.eq("id",id)
                .set("vip_status",2);
        if (result > 0){
            wrapper.set("vip_status", 1);
        }
        this.update(wrapper);
        return ResultUtil.success();
    }

    /**
     * 添加会员
     */

    @Override
    public ResultMessage<Object> add(VipDto dto) {
        //return addVip(dto);
        saveVipFlowByCode(dto.getUserId(),dto.getTimeType(), "");
        return ResultUtil.success();
    }

    @Override
    public ResultMessage<LiVipVo> getVipDetail() {
        if (UserContext.getCurrentId() == null) {
            throw new ServiceException("请登录后重试");
        }
        LiVip liVip = super.getOne(new LambdaQueryWrapper<LiVip>()
                .eq(LiVip::getUserId, UserContext.getCurrentId()).eq(LiVip::getDeleteFlag, false)
                .orderByDesc(LiVip::getCreateTime)
                .last("limit 1"));

        LiVipVo res = new LiVipVo();
        if (liVip != null) {
            BeanUtil.copyProperties(liVip, res);
            res.setEndTimeLong(liVip.getEndTime().getTime());
            Map<String, Object> objectMap = orderClient.getSumPrice();
            res.setSumPrice((Double) objectMap.get("vipPrice"));
        }
        return ResultUtil.data(res);
    }

    @Override
    public ResultMessage<Object> vipExtend(VipDto dto) {
        if ((Objects.isNull(dto.getTimeType()))||(StringUtils.isEmpty(dto.getUserId())))
            throw new ServiceException(ResultCode.PARAMS_ERROR);

        LiVip liVip = vipMapper.selectByUserId(dto.getUserId());

        if ((VipStatusEnum.FREEZE.getStatus()).equals(liVip.getVipStatus())||
        (VipStatusEnum.URBAN_FREEZE.getStatus()).equals(liVip.getVipStatus())){
            throw new ServiceException(ResultCode.FREEZE_USER);
        }
        if ((VipStatusEnum.EXPIRED.getStatus()).equals(liVip.getVipStatus())){
            Calendar calendar=Calendar.getInstance();
            return getResult(dto, liVip, calendar);
        }

        if ((VipStatusEnum.NORMAL.getStatus()).equals(liVip.getVipStatus())){
            Calendar calendar=Calendar.getInstance();
            calendar.setTime(liVip.getEndTime());
            return getResult(dto, liVip, calendar);
        }
        return ResultUtil.error();
    }

    @Override
    public List<LiVip> getNormalVip() {
        LambdaQueryWrapper<LiVip>wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(LiVip::getVipStatus,VipStatusEnum.NORMAL.getStatus());
        return vipMapper.selectList(wrapper);
    }


    private ResultMessage<Object> addVip(VipDto dto) {
        /**
         * 1.数值判断:timeType、userId
         *  用户不存在不可操作
         * 2.冻结状态不可操作
         * 3.该userid不是plus会员或者过期状态将过期时间改为现在时间+有效期
         * 4.正常状态将到期时间+有效期
         * 5.添加完成时，流水表记录该次操作
         */
        if ((Objects.isNull(dto.getTimeType()))||(StringUtils.isEmpty(dto.getUserId())))
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        User user = userService.getById(dto.getUserId());
        if (Objects.isNull(user))
            throw new ServiceException(ResultCode.USER_NOT_EXIST);
        LiVip liVip = this.getById(dto.getUserId());

        if (liVip==null){
            Calendar calendar=Calendar.getInstance();
            calendar.add(Calendar.MONTH,dto.getTimeType());
            LiVip liVip1 = LiVip.builder()
                    .userId(dto.getUserId())
                    .vipStatus(VipStatusEnum.NORMAL.getStatus())
                    .openingMode(PayWayEnum.MANAGE_ADD.getValue())
                    .userName(user.getUsername())
                    .endTime(calendar.getTime())
                    .phone(user.getMobile())
                    .build();
            liVip1.setCreateBy(UserContext.getCurrentId());
            liVip1.setCreateTime(Date.from(Instant.now()));
            this.save(liVip1);

            saveVipFlow(dto,user);
            return ResultUtil.success();

        }
        else
            return ResultUtil.error(400,"该用户已开通会员");
    }

    private void saveVipFlow(VipDto dto, User user) {
        //记录流水
        LiVipFlow vipFlow = LiVipFlow.builder()
                .userId(dto.getUserId())
                .userName(user.getUsername())
                .flowType(PayWayEnum.MANAGE_ADD.getValue())
                .build();
        String remark = vipFlow.addRemark(LocalDate.now(), PayWayEnum.MANAGE_ADD.name());
        vipFlow.setCreateBy(UserContext.getCurrentId());
        vipFlow.setCreateTime(Date.from(Instant.now()));
        vipFlow.setRemark(remark);
        flowService.save(vipFlow);
    }

    private ResultMessage<Object> getResult(VipDto dto, LiVip liVip, Calendar calendar) {

        calendar.add(Calendar.MONTH, dto.getTimeType());
        UpdateWrapper<LiVip> wrapper = new UpdateWrapper<LiVip>();
        wrapper.eq("user_id", liVip.getUserId())
                .set("end_time", calendar.getTime())
                .set("vip_status",VipStatusEnum.NORMAL.getStatus())
                .set("opening_mode", PayWayEnum.MANAGE_ADD.getValue())
                .set("update_by", UserContext.getCurrentId())
                .set("update_time", DateTime.now());
        this.update(wrapper);

        //记录流水
        LiVipFlow vipFlow = LiVipFlow.builder()
                .userName(liVip.getUserName())
                .userId(liVip.getUserId())
                .flowType(PayWayEnum.MANAGE_ADD.getValue())
                .build();
        String remark = vipFlow.addRemark(LocalDate.now(), PayWayEnum.MANAGE_ADD.name());
        vipFlow.setRemark(remark);
        vipFlow.setCreateBy(UserContext.getCurrentId());
        vipFlow.setCreateTime(Date.from(Instant.now()));
        flowService.save(vipFlow);
        return ResultUtil.success();
    }

    public void activeVipByCode (String code) {
        LiVipActiveCode vipActiveCode = vipActiveCodeService.getActiveCodeByCode(code);
        if (null == vipActiveCode) {
            throw new ServiceException("激活码无效");
        }
        saveVipFlowByCode(UserContext.getCurrentId(), vipActiveCode.getTimeType(), code);
        vipActiveCodeService.updateCodeStatus(vipActiveCode, UserContext.getCurrentId());
    }

    public void saveVipFlowByCode (String payerId, Integer timeType, String code) {
        LiVip vip = getByUserId(payerId);
        boolean flag = false;
        User user = userService.getById(payerId);
        LiVipConfig vipConfig = vipConfigClient.getByDefault();
        if (null != vip) {
            if (vip.getVipStatus()==3||vip.getVipStatus()==4){
                throw new ServiceException("该用户已被冻结，操作失败");
            }
            Calendar calendar = Calendar.getInstance();
            // 会员有效时间小于等于当前时间，表示已过期
            if (vip.getEndTime().after(calendar.getTime())) {
                calendar.setTime(vip.getEndTime());
                calendar.add(Calendar.MONTH, timeType);
                Date endTime = calendar.getTime();
                vip.setEndTime(endTime);
            }else {
                calendar.add(Calendar.MONTH, timeType);
                Date endTime = calendar.getTime();
                vip.setEndTime(endTime);
            }
            vip.setVipStatus(1);
            vip.setOpeningMode(CharSequenceUtil.isNotEmpty(code) ? 5 : 6);
            vip.setVipName(vipConfig.getVipName());
            vip.setVipId(Long.valueOf(vipConfig.getId()));
            vip.setUpdateTime(new Date());
            this.baseMapper.updateById(vip);
            flag = true;
        }else {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, timeType);
            Date endTime = calendar.getTime();
            vip = LiVip.builder()
                    .vipName(vipConfig.getVipName())
                    .vipId(Long.valueOf(vipConfig.getId()))
                    .vipStatus(1)
                    .activeCode(CharSequenceUtil.isNotEmpty(code) ? code : "")
                    .endTime(endTime)
                    .userId(payerId)
                    .userName(null != user && CharSequenceUtil.isNotEmpty(user.getUsername()) ? user.getUsername() : null)
                    .phone(null != user && CharSequenceUtil.isNotEmpty(user.getMobile()) ? user.getMobile() : null)
                    .openingMode(CharSequenceUtil.isNotEmpty(code) ? 5 : 6)
                    .build();
            this.baseMapper.insert(vip);
        }
        LiVipFlow vipFlow = LiVipFlow.builder()
                .flowType(CharSequenceUtil.isNotEmpty(code) ? 5 : 6)
                .payPrice(BigDecimal.ZERO)
                .payTime(new Date())
                .vipConfigId(vipConfig.getId())
                .remark(flag ? "续费会员" : "开通会员")
                .userId(payerId)
                .activeCode(code)
                .vipConfigName(vipConfig.getVipName())
                .userName(null != user && CharSequenceUtil.isNotEmpty(user.getUsername()) ? user.getUsername() : null)
                .addTime(timeType)
                .build();
        flowService.save(vipFlow);
    }

    public void saveVipFlow (String payerId, String paymentMethod, Double price) {
        Integer openingMode = switch (paymentMethod) {
            case "WECHAT" -> 1;
            case "ALIPAY" -> 2;
            case "CODE" -> 5;
            case "APPLE" -> 7;
            default -> null;
        };
        LiVip vip = getByUserId(payerId);
        boolean flag = false;
        User user = userService.getById(payerId);
        LiVipConfig vipConfig = vipConfigClient.getByDefault();
        if (null != vip) {
            if (vip.getVipStatus()==3||vip.getVipStatus()==4){
                throw new ServiceException("该用户已被冻结，操作失败");
            }
            Calendar calendar = Calendar.getInstance();
            // 会员有效时间小于当前时间，表示已过期
            if (vip.getEndTime().before(new Date())) {
                calendar.add(Calendar.YEAR, 1);
                Date endTime = calendar.getTime();
                vip.setEndTime(endTime);
            }else {
                calendar.setTime(vip.getEndTime());
                calendar.add(Calendar.YEAR, 1);
                Date endTime = calendar.getTime();
                vip.setEndTime(endTime);
            }
            vip.setVipStatus(1);
            vip.setOpeningMode(openingMode);
            vip.setVipName(vipConfig.getVipName());
            vip.setVipId(Long.valueOf(vipConfig.getId()));
            vip.setUpdateTime(new Date());
            this.baseMapper.updateById(vip);
            flag = true;
        }else {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.YEAR, 1);
            Date endTime = calendar.getTime();
            vip = LiVip.builder()
                    .vipName(vipConfig.getVipName())
                    .vipId(Long.valueOf(vipConfig.getId()))
                    .vipStatus(1)
                    .endTime(endTime)
                    .userId(payerId)
                    .userName(null != user && CharSequenceUtil.isNotEmpty(user.getUsername()) ? user.getUsername() : null)
                    .phone(null != user && CharSequenceUtil.isNotEmpty(user.getMobile()) ? user.getMobile() : null)
                    .openingMode(openingMode)
                    .build();
            this.baseMapper.insert(vip);
        }
        LiVipFlow vipFlow = LiVipFlow.builder()
                .flowType(openingMode)
                .payPrice(BigDecimal.valueOf(price))
                .payTime(new Date())
                .vipConfigId(vipConfig.getId())
                .remark(flag ? "续费会员" : "开通会员")
                .userId(payerId)
                .vipConfigName(vipConfig.getVipName())
                .userName(null != user && CharSequenceUtil.isNotEmpty(user.getUsername()) ? user.getUsername() : null)
                .addTime(vipConfig.getDefaultTime())
                .build();
        flowService.save(vipFlow);
    }


    @Override
    public LiVip getByUserId(String userId) {
        LiVip liVip = this.baseMapper.selectOne(new LambdaQueryWrapper<LiVip>().eq(LiVip::getUserId, userId)
                .eq(LiVip::getDeleteFlag, false)
                .orderByDesc(LiVip::getCreateTime)
                .last("limit 1"));
        if (liVip != null) {
            liVip.setEndTimeTow(liVip.getEndTime());
        }
        return liVip;
    }
}




